﻿using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.Client;
using NetProtocol.POD;

namespace IQIGame.Onigao.GamePlay
{
    public class EquipmentModule : Singleton<EquipmentModule>, CNetEquip
    {
        private EquipmentModule() { }

        public void InitModule(PlayerPOD playerPOD)
        {
            GameDataCenter.PlayerData.equipSkins = playerPOD.equipSkins;
        }

        public void ClearModule()
        {
            GameDataCenter.PlayerData.equipSkins = null;
        }

        #region Net层
        static public CNetEquip NetCore => Instance;

        public ISession GetSession()
        {
            return GameServerModule.Instance.CurrSession;
        }

        void CNetEquip.SC_notifySkinActive(ISession session, int skinCid)
        {
            var list = GameDataCenter.PlayerData.equipSkins;
            if (!list.Contains(skinCid))
                list.Add(skinCid);
        }

        #endregion

        public bool IsHasEquipSkin(int cid)
        {
            var list = GameDataCenter.PlayerData.equipSkins;
            return list != null && list.Contains(cid);
        }

        /// <summary>
        /// 反向取得升级升星到当前装备星级和等级时需要的消耗
        /// </summary>
        private bool CalcReUpStarLvCosts(ItemEquipmentData equipData, ref Dictionary<int, int> ret)
        {
            if (equipData.level == 1 && equipData.star == 1)
                return false;

            if (ret == null)
                ret = new(4);

            // 升星材料
            for (int i = 1; i < equipData.star; i++)
            {
                var cfg = TableCenter.equipStar.GetCfg(equipData.cid, i);
                if (cfg == null)
                    continue;
                for (int j = 0, cntItems = cfg.CostItems.Count; j < cntItems; j += APIUIEquip.OneCostItemCount)
                {
                    ret.TryGetValue(cfg.CostItems[j], out int costNum);
                    costNum += cfg.CostItems[j + 1];
                    ret[cfg.CostItems[j]] = costNum;
                }

                if (cfg.CostBasicEquipNum > 0)
                {
                    ret.TryGetValue(equipData.cid, out int equipNum);
                    ret[equipData.cid] = equipNum + cfg.CostBasicEquipNum;
                }
            }

            // 升级材料
            int expAll = 0;
            for (int i = 1; i < equipData.level; i++)
            {
                var cfg = TableCenter.equipLevel.Get(i);
                expAll += cfg.NextExp;
            }

            if (expAll > 0)
            {
                // 金币
                var listMoney = APIUIEquip.UpLvCostMoney;
                if (listMoney.Count == APIUIEquip.OneCostItemCount)
                {
                    ret.TryGetValue(listMoney[0], out int costNum);
                    costNum += listMoney[1] * expAll;
                    ret[listMoney[0]] = costNum;
                }

                var list = APIUIEquip.UpLvCostItems;
                int cnt = list.Count / APIUIEquip.OneCostItemCount;
                int kStart = (cnt - 1) * APIUIEquip.OneCostItemCount;
                if (kStart >= 0)
                {
                    int expOne = 0;
                    while (expAll > 0 && kStart >= 0)
                    {
                        expOne = list[kStart + 1];
                        if (expOne > expAll)
                        {
                            kStart -= APIUIEquip.OneCostItemCount;
                            continue;
                        }
                        expAll -= expOne;
                        ret.TryGetValue(list[kStart], out int costNum);
                        costNum++;
                        ret[list[kStart]] = costNum;
                    }
                }
            }

            return true;
        }

        /// <summary>
        /// 重生返还
        /// </summary>
        public Dictionary<int, int> CalcRebornCosts(ItemEquipmentData equipItem)
        {
            Dictionary<int, int> ret = null;
            if (!this.CalcReUpStarLvCosts(equipItem, ref ret))
                return null;
            ret.TryGetValue(equipItem.cid, out int equipCount);
            ret[equipItem.cid] = equipCount + 1;
            return ret;
        }

        /// <summary>
        /// 分解返还
        /// </summary>
        private void CalcDecomposeCosts(ItemEquipmentData equipItem, ref Dictionary<int, int> ret)
        {
            this.CalcReUpStarLvCosts(equipItem, ref ret);
            if (ret == null)
                ret = new();
            ret.TryGetValue(equipItem.cid, out int equipCount);
            ret.Remove(equipItem.cid);
            equipCount++;

            var list = equipItem.cfgData.DecomposeReward;
            int cntRwd = list.Count / APIUIEquip.OneCostItemCount;
            for (int i = 0; i < cntRwd; i++)
            {
                ret.TryGetValue(list[i], out int costNum);
                costNum += list[i + 1] * equipCount;
                ret[list[i]] = costNum;
            }
        }

        public void CalcDecomposeCosts(List<long> equipIds, ref Dictionary<int, int> ret)
        {
            if (equipIds == null || equipIds.Count == 0)
                return;
            if (ret == null)
                ret = new(8);
            foreach (long id in equipIds)
            {
                ItemEquipmentData equipItem = ItemModule.Instance.GetItemById(id) as ItemEquipmentData;
                if (equipItem == null)
                    continue;
                this.CalcDecomposeCosts(equipItem, ref ret);
            }
        }
    }
}
